package com.zhang.controller.file;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhang.common.oss.minio.FileInfoVo;
import com.zhang.common.util.result.R;
import com.zhang.common.util.result.REnum;
import com.zhang.common.util.result.RUtils;
import com.zhang.file.dto.FileSearchDTO;
import com.zhang.file.entity.Files;
import com.zhang.file.service.IFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import static org.apache.tomcat.util.http.fileupload.IOUtils.copy;

@Slf4j
@RestController
@RequestMapping("/my/file")
public class FileController {
    @Autowired
    private IFileService fileService;

    @GetMapping("get/byId")
    public void getImageByFileId(Long fileId, HttpServletRequest request, HttpServletResponse response) {
        log.info("访问系统文件");
        Files file = fileService.getById(fileId);
        if (file != null) {
            InputStream inputStream = fileService.getFile(file.getFileBucket(), file.getFileUrl());
            try {
                response.setContentType(file.getFileType());
                copy(inputStream, response.getOutputStream());
            } catch (IOException e) {
                log.error("这里有异常", e);
            }
        }
    }

    @GetMapping("video/{fileId}")
    public void getVideoByFileId(@PathVariable Long fileId, HttpServletRequest request, HttpServletResponse response) {
        Files file = fileService.getById(fileId);
        Long fileSize = file.getFileSize();
        if (file == null || fileSize == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        String rangeHeader = request.getHeader(HttpHeaders.RANGE);
        if (rangeHeader == null || !rangeHeader.startsWith("bytes=")) {
            // 如果没有Range请求，则返回整个文件
            try (InputStream inputStream = fileService.getFile(file.getFileBucket(), file.getFileUrl())) {
                response.setHeader("Content-Length", String.valueOf(fileSize));
                response.setContentType(file.getFileType());
                copy(inputStream, response.getOutputStream());
            } catch (IOException e) {
                log.error("报异常啦", e);
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            return;
        }
        // 处理Range请求
        long start = 0;
        long end = fileSize - 1;
        String[] rangeValues = rangeHeader.substring(6).split("-");
        if (rangeValues.length > 0) {
            start = Long.parseLong(rangeValues[0]);
        }
        if (rangeValues.length > 1 && !rangeValues[1].isEmpty()) {
            end = Long.parseLong(rangeValues[1]);
        }
        if (end >= fileSize) {
            end = fileSize - 1;
        }

        long contentLength = end - start + 1;
        try (InputStream inputStream = fileService.getFile(file.getFileBucket(), file.getFileUrl())) {
            // 跳过开始部分
            inputStream.skip(start);
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            response.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + fileSize);
            response.setHeader("Accept-Ranges", "bytes");
            response.setHeader("Content-Length", String.valueOf(contentLength));
            response.setContentType(file.getFileType());
            byte[] buffer = new byte[1024 * 8]; // 使用更大的缓冲区提高性能
            int read;
            OutputStream outputStream = response.getOutputStream();
            while ((read = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, read);
            }
            outputStream.flush();
        } catch (IOException e) {
            log.error("Error while reading the file", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    private void copy(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024 * 1024]; // 使用更大的缓冲区提高性能
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
    }

    @GetMapping("getAllFileBucket")
    public R getAllFileBucket() {
        try {
            List<String> allFileBucket = fileService.getAllFileBucket();
            return RUtils.successData(allFileBucket);
        } catch (Exception e) {
            log.info("桶获取失败：---->", e);
            return RUtils.resultEnum(REnum.RESOURCE_NOT_EXIST);
        }
    }
    @GetMapping("getFilesFromBucket")
    public R searchFile(FileSearchDTO searchDTO) {
        try {
            Page list = fileService.getFileFromBucket(searchDTO);
            return RUtils.successData(list);
        } catch (Exception e) {
            log.info("桶内文件信息获取失败:------->", e);
            return RUtils.resultEnum(REnum.RESOURCE_NOT_EXIST);
        }
    }

    /**
     * 只需要传入桶名和文件夹就可以了
     * 文件夹名不需要加/
     * 图片上传
     *
     * @param files
     * @param fileInfo
     * @return {@link R}
     */
    @PostMapping("upFile")
    public R upFile(MultipartFile[] files, FileInfoVo fileInfo) {
        log.info("上传数据是:-->{}", fileInfo);
        /*判断上传的类型*/
        List<Long> filesId = new ArrayList<>();
        if (files.length == 0) {
            log.error("上传的文件是空的");
            return RUtils.err("上传失败");
        }
        for (MultipartFile file : files) {
            Files filesInfo = fileService.uploadFile(file, fileInfo);
            filesId.add(filesInfo.getId());
        }
        if (filesId.size() > 1) {
            return RUtils.successDataMsg(filesId, "上传成功");
        }
        return RUtils.successData(filesId.get(0));
    }

    @PostMapping("del/byIds")
    public R delFileByFileId(@RequestBody List<Long> fileIds) {
        fileService.delFileByFileId(fileIds);
        return RUtils.successMsg("删除成功");
    }
}
